package com.seguriapp.complaints.gwt.client;

import java.util.List;

import com.google.gwt.cell.client.Cell.Context;
import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.ColumnSortEvent.AsyncHandler;
import com.google.gwt.user.cellview.client.ColumnSortList;
import com.google.gwt.user.cellview.client.RowStyles;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.AsyncDataProvider;
import com.google.gwt.view.client.HasData;
import com.seguriapp.common.gwt.client.UtilClientValidations;
import com.seguriapp.common.gwt.client.celltable.HyperLinkColumn;
import com.seguriapp.common.gwt.client.celltable.SeguriAppCellTable;
import com.seguriapp.common.gwt.client.pagination.SearchPagination;
import com.seguriapp.common.gwt.client.searchfilter.SearchFilter;
import com.seguriapp.complaints.gwt.client.activity.ComplaintsListActivity;
import com.seguriapp.complaints.gwt.client.activity.ComplaintsListActivity.Display;
import com.seguriapp.entities.Complaint;

public class ComplaintsListPage extends Composite implements Display {

  private static final String NEW_COMPLAINTS = " nueva(s) denuncia(s)";

  private static ComplaintsListPageUiBinder uiBinder = GWT.create(ComplaintsListPageUiBinder.class);

  interface ComplaintsListPageUiBinder extends UiBinder<Widget, ComplaintsListPage> {
  }

  @UiField
  protected HTMLPanel complaintsGridPanel;
  @UiField
  protected SearchFilter searchFilter;
  @UiField
  protected InlineLabel noDataLabel;
  @UiField
  protected SearchPagination pagination;
  @UiField
  protected Anchor showNewComplaintsLink;

  private CellTable<Complaint> complaintsGrid;
  private TextColumn<Complaint> namesColumn;
  private TextColumn<Complaint> dniColumn;
  private TextColumn<Complaint> dateColumn;
  private TextColumn<Complaint> policeStationColumn;
  private Column<Complaint, String> viewDetailColumn;

  private ComplaintsListActivity presenter;

  public ComplaintsListPage() {
    initWidget(uiBinder.createAndBindUi(this));
    initializeColumns();
    initializeDataGrid();
    initializeHandlers();
  }

  public void setPresenter(final ComplaintsListActivity presenter) {
    this.presenter = presenter;
  }

  private void initializeColumns() {
    namesColumn = new TextColumn<Complaint>() {

      @Override
      public String getValue(final Complaint complaint) {
        return complaint.getNames().concat(" ").concat(complaint.getLastNames());
      }
    };

    dniColumn = new TextColumn<Complaint>() {

      @Override
      public String getValue(final Complaint complaint) {
        return complaint.getDni();
      }
    };

    dateColumn = new TextColumn<Complaint>() {

      @Override
      public String getValue(final Complaint complaint) {
        return UtilClientValidations.DATE_VIEW_FORMAT.format(complaint.getCrimeDate());
      }
    };

    policeStationColumn = new TextColumn<Complaint>() {

      @Override
      public String getValue(final Complaint complaint) {
        return complaint.getPoliceStation().getTitle();
      }
    };

    viewDetailColumn = new HyperLinkColumn<Complaint>() {

      @Override
      public String getValue(final Complaint complaint) {
        return "";
      }

      @Override
      public void render(final Context context, final Complaint complaint, final SafeHtmlBuilder sb) {
        setTooltip("Ver Detalle");
        setStyle("detailsIcon");
        super.render(context, complaint, sb);
      }

    };
    namesColumn.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
    dniColumn.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
    dateColumn.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
    policeStationColumn.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);

    viewDetailColumn.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);

    namesColumn.setSortable(true);
    dniColumn.setSortable(true);
    dateColumn.setSortable(true);
    policeStationColumn.setSortable(true);
    viewDetailColumn.setFieldUpdater(new FieldUpdater<Complaint, String>() {

      public void update(final int index, final Complaint complaint, final String value) {
        presenter.goToComplaintDetailsPage(complaint);
      }
    });

  }

  private void initializeHandlers() {
    AsyncDataProvider<Complaint> dataProvider = new AsyncDataProvider<Complaint>() {

      @Override
      protected void onRangeChanged(HasData<Complaint> display) {

        // Get the ColumnSortInfo from the table.
        final ColumnSortList sortList = complaintsGrid.getColumnSortList();
        if (sortList.size() > 0) {
          presenter.setAscending(sortList.get(0).isAscending());
          if (sortList.get(0).getColumn().equals(namesColumn)) {
            presenter.setColumnSort("names");
          } else if (sortList.get(0).getColumn().equals(dniColumn)) {
            presenter.setColumnSort("dni");
          } else if (sortList.get(0).getColumn().equals(dateColumn)) {
            presenter.setColumnSort("crimeDate");
          } else if (sortList.get(0).getColumn().equals(policeStationColumn)) {
            presenter.setColumnSort("entity.id");
          }
          presenter.updateComplaintsList();
        }
      }
    };

    dataProvider.addDataDisplay(complaintsGrid);

    // Add a ColumnSortEvent.AsyncHandler to connect sorting to the
    // AsyncDataPRrovider.
    AsyncHandler columnSortHandler = new AsyncHandler(complaintsGrid);
    complaintsGrid.addColumnSortHandler(columnSortHandler);

  }

  private void generateTable() {
    complaintsGrid = new SeguriAppCellTable<Complaint>();
    complaintsGrid.addColumn(namesColumn, "Nombres");
    complaintsGrid.addColumn(dniColumn, "DNI");
    complaintsGrid.addColumn(dateColumn, "Fecha");
    complaintsGrid.addColumn(policeStationColumn, SafeHtmlUtils.fromTrustedString("Comisar&iacute;a"));
    complaintsGrid.addColumn(viewDetailColumn, "Detalle");
    complaintsGrid.setColumnWidth(namesColumn, "30%");
    complaintsGrid.setColumnWidth(dniColumn, "20%");
    complaintsGrid.setColumnWidth(dateColumn, "20%");
    complaintsGrid.setColumnWidth(policeStationColumn, "30%");
    complaintsGrid.setColumnWidth(viewDetailColumn, "20%");
  }

  private void initializeDataGrid() {
    generateTable();
    complaintsGridPanel.clear();
    complaintsGridPanel.add(complaintsGrid);
  }

  public void setGridData(final List<Complaint> complaintsList) {
    noDataLabel.setVisible(false);
    complaintsGridPanel.setVisible(true);
    complaintsGrid.setRowData(0, complaintsList);
    complaintsGrid.setRowCount(complaintsList.size(), true);
    complaintsGrid.setRowStyles(new RowStyles<Complaint>() {

      public String getStyleNames(final Complaint row, final int rowIndex) {
        return row.isNewComplaint() ? "newComplaint" : null;
      }
    });
    final Timer t = new Timer() {

      @Override
      public void run() {
        complaintsGrid.setRowStyles(null);
        complaintsGrid.setRowData(0, complaintsList);
        complaintsGrid.setRowCount(complaintsList.size(), true);
      }
    };

    // Schedule the timer to run in 3 seconds.
    t.schedule(3000);
  }

  public SearchFilter getSearchFilter() {
    return searchFilter;
  }

  public SearchPagination getPagination() {
    return pagination;
  }

  public void showNoDataMessage() {
    noDataLabel.setVisible(true);
    complaintsGridPanel.setVisible(false);
  }

  public void showNewComplaintsLink(final int complaintsCount) {
    if (complaintsCount > 0) {
      showNewComplaintsLink.setText(complaintsCount + NEW_COMPLAINTS);
      showNewComplaintsLink.setVisible(true);
    } else {
      showNewComplaintsLink.setVisible(false);
    }
  }

  public void setPagination(final long currentPage, final long totalPages, final long maxPages) {
    pagination.setPagination(currentPage, totalPages, maxPages);
  }

  @UiHandler("showNewComplaintsLink")
  protected void onShowNewComplaintsLinkClick(final ClickEvent event) {
    showNewComplaintsLink.setVisible(false);
    presenter.showNewComplaints();
  }
}
